package com.yjb.tenet.boot.system.application.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.lang.tree.Tree;
import cn.hutool.core.lang.tree.TreeNode;
import cn.hutool.core.lang.tree.TreeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.yjb.tenet.boot.common.constants.GlobalConstants;
import com.yjb.tenet.boot.system.application.checker.SysDeptChecker;
import com.yjb.tenet.boot.system.application.convert.SysDeptConvert;
import com.yjb.tenet.boot.system.application.service.SysDeptRelationService;
import com.yjb.tenet.boot.system.application.service.SysDeptService;
import com.yjb.tenet.boot.system.domain.entity.SysDept;
import com.yjb.tenet.boot.system.domain.entity.SysDeptRelation;
import com.yjb.tenet.boot.system.domain.form.SysDeptAddForm;
import com.yjb.tenet.boot.system.domain.form.SysDeptEditForm;
import com.yjb.tenet.boot.system.domain.vo.SysDeptVO;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;


/**
 * @author zpc
 * @version 1.0
 * @description 部门manager
 * @create 2022/5/23 9:31
 */
@Component
public class SysDeptManager {

	private static final Long TREE_ROOT_ID = 0L;

	@Resource
    private SysDeptService sysDeptService;

    @Resource
    private SysDeptRelationService sysDeptRelationService;

	@Resource
	private SysDeptChecker sysDeptChecker;


	/**
	 * 完整部门树
	 */
	public List<Tree<Long>> treeDept() {
		List<SysDept> sysDepts = sysDeptService.lambdaQuery()
				.eq(SysDept::getDeleted, GlobalConstants.NOT_DELETED)
				.orderByAsc(SysDept::getOrderNo)
				.list();
		List<TreeNode<Long>> collect = sysDepts.stream().map(getNodeFunction()).collect(Collectors.toList());
		return TreeUtil.build(collect, TREE_ROOT_ID);
	}

	/**
	 * 新增部门
	 * @param form
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public boolean save(SysDeptAddForm form) {
		SysDept sysDept = SysDeptConvert.INSTANCE.convert(form);

		// 给部门添加完整路径
		Long parentId = sysDept.getParentId();
		if(parentId.equals(TREE_ROOT_ID)){
			sysDept.setDeptAlias(sysDept.getDeptName());
		}else{
			SysDept parentDept = sysDeptService.getById(sysDept.getParentId());
			sysDept.setDeptAlias(parentDept.getDeptAlias()+">"+sysDept.getDeptName());
		}
		sysDeptService.save(sysDept);
		// 增加关系表
		return sysDeptRelationService.saveDeptRelation(sysDept);
	}

	/**
	 * 编辑部门
	 * @param form
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public boolean edit(SysDeptEditForm form) {
		SysDept one = sysDeptService.lambdaQuery()
				.eq(SysDept::getDeleted, GlobalConstants.NOT_DELETED)
				.eq(SysDept::getDeptId, form.getDeptId()).one();

		BeanUtil.copyProperties(form, one);
		sysDeptService.updateById(one);
		// 找到该节点及所有子孙结点，修改其别名
		// 旧别名
		String oldDeptAlias = one.getDeptAlias();
		// 新别名
		String newDeptAlias = form.getDeptName();
		if(!form.getParentId().equals(TREE_ROOT_ID)){
			SysDept parentDept = sysDeptService.getById(form.getParentId());
			newDeptAlias = parentDept.getDeptAlias() + ">" + form.getDeptName();
		}
		// 构造新的别名
		List<SysDeptRelation> list = sysDeptRelationService.lambdaQuery().eq(SysDeptRelation::getAncestor, one.getDeptId()).list();
		List<SysDept> listDept = new ArrayList<>();
		for (SysDeptRelation sysDeptRelation:list) {
			SysDept sysDept = sysDeptService.getById(sysDeptRelation.getDescendant());
			sysDept.setDeptAlias(StrUtil.replace(sysDept.getDeptAlias(), oldDeptAlias, newDeptAlias));
			listDept.add(sysDept);
		}
		sysDeptService.updateBatchById(listDept);
		// 更新关系
		SysDeptRelation relation = new SysDeptRelation();
		relation.setAncestor(one.getParentId());
		relation.setDescendant(one.getDeptId());
		return sysDeptRelationService.updateDeptRelation(relation);
	}

	/**
	 * 删除部门
	 *
	 * @param id 部门id
	 */
	@Transactional(rollbackFor = Exception.class)
	public boolean delete(Long id) {
		SysDept sysDept = sysDeptChecker.checkForDelete(id);
		sysDept.setDeleted(id);
		sysDeptService.updateById(sysDept);
		// 删除部门关系表
		return sysDeptRelationService.remove(Wrappers.<SysDeptRelation>query().lambda().eq(SysDeptRelation::getDescendant, id));
	}

    /**
     * 根据名字搜索部门
     */
    public List<SysDeptVO> list(String name) {
		List<SysDept> list = sysDeptService.lambdaQuery()
				.eq(SysDept::getDeleted, GlobalConstants.NOT_DELETED)
				.like(SysDept::getDeptName, name)
				.orderByAsc(SysDept::getOrderNo)
				.list();

		return SysDeptConvert.INSTANCE.convert(list);
    }

	@NotNull
	private Function<SysDept, TreeNode<Long>> getNodeFunction() {
		return SysDept -> {
			TreeNode<Long> node = new TreeNode<>();
			node.setId(SysDept.getDeptId());
			//node.setName(SysDept.getDeptName());
			node.setParentId(SysDept.getParentId());
			node.setWeight(SysDept.getOrderNo());
			// 扩展属性
			Map<String, Object> extra = new HashMap<>();
			extra.put("deptId", SysDept.getDeptId());
			extra.put("deptName", SysDept.getDeptName());
			extra.put("deptLeader", SysDept.getDeptLeader());
			extra.put("orderNo", SysDept.getOrderNo());
			extra.put("remark", SysDept.getRemark());
			extra.put("createTime", LocalDateTimeUtil.format(SysDept.getCreateTime(), "yyyy-MM-dd HH:mm:ss"));
			node.setExtra(extra);
			return node;
		};
	}

}
